#pragma once
#include <iostream>
#include "Epoller.hpp"
#include "Connection.hpp"
#include <memory>
#include <unordered_map>
#include "Log.hpp"
class Reactor
{
    static const int MAX_EVENTS = 128;

public:
    Reactor() : epoller(std::make_unique<Epoller>()), isRunning(false) {}
    ~Reactor() {}
    void Loop()
    {
        if (Isconnectionempty())
        {
            return;
        }
        isRunning = true;
        while (true)
        {
            PrintF();
            int timeout = -1;
            int n=LoopOnce(timeout);
            Dispatch(n);
        }
        isRunning = false;
    }
    void PrintF(){
        std::cout<<"connections:";
        for(auto i :connections){
            std::cout<<i.first<<" ";
        }
        std::cout<<std::endl;
    }
    void stop()
    {
        isRunning = false;
    }
    void Deleteconnection(int sockfd){
        if (IsConnectionExist(sockfd))
        {
            connections.erase(sockfd);
            epoller->DelEvent(sockfd);
            close(sockfd);
            LOG(LogLevel::INFO) << "删除连接成功" << sockfd;
        }
    }
    // 该接口要把所有的新连接添加到connections中进行管理，并写透到内核中
    void Addconnection(std::shared_ptr<Connection> &conn)
    {
        if (IsConnectionExist(conn->getFd()))
        {
            LOG(LogLevel::WARNING) << "该连接已存在，无法添加";
            return;
        }
        // 1.conn_>fd和evenet写透到内核
        uint32_t event = conn->getEvents();
        int sockfd = conn->getFd();
        epoller->AddEvent(sockfd, event);
        //设置当前conn的tcpserver
        conn->setOwner(this);
        // 将conn添加到connections中进行管理
        connections[sockfd] = conn;
    }
    void EnableReadWrite(int sockfd,bool enableread,bool enablewrite){
        if(!IsConnectionExist(sockfd)){
            LOG(LogLevel::WARNING) << "该连接不存在，无法设置读写状态";
            return;
        }
        //修改sockfd对应的connection关心的事件
        uint32_t event = (EPOLLET|enableread ? EPOLLIN:0|enablewrite?EPOLLOUT:0);
        connections[sockfd]->setEvents(event);
        //写透到内核
        epoller->ModEvent(sockfd, event);
    }
private:
    bool IsConnectionExist(int fd)
    {
        return connections.find(fd) != connections.end();
    }
    bool Isconnectionempty()
    {
        return connections.empty();
    }
    int LoopOnce(int timeout)
    {
        int n = epoller->WaitEvent(events, MAX_EVENTS, timeout);
        return n;
    }
    void Dispatch(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int sockfd = events[i].data.fd;
            uint32_t event = events[i].events;
            // 将所有的异常处理转化为IO错误
            if (event & EPOLLIN)
            {
                // 1.如果有数据到来，则处理数据
                // 2.不用区分是新连接还是数据
                if (IsConnectionExist(sockfd))
                {
                    auto conn = connections[sockfd];
                    conn->Recever();
                }
            }
            if (event & EPOLLOUT)
            {
                // 2.如果有数据需要发送，则发送数据
                if (IsConnectionExist(sockfd))
                {
                    auto conn = connections[sockfd];
                    conn->Sender();
                }
            }
            if ((event & EPOLLHUP) || (event & EPOLLERR))
            {
                // 将所有错误处理转化为IO错误
                event |= EPOLLIN | EPOLLOUT;
            }
        }
    }
    

private:
    bool isRunning;
    // 1.epoll模块
    std::unique_ptr<Epoller> epoller;
    // 2.管理fd,管理获取的fd
    std::unordered_map<int, std::shared_ptr<Connection>> connections;
    // 就绪的所有事件
    struct epoll_event events[MAX_EVENTS];
};